package ihm;

import image.FormDetector2;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.smartcardio.CardException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;

import application.LeGroupe4Biometric;
import application.smartcard.SmartCard;

import security.AES256;
import security.HMAC;

import database.bean.AuthCardData;
import database.bean.User;
import database.hibernate.HibernateUtil;

public class InitialisationFrame extends JFrame {

	/**
		 * 
		 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JPasswordField passwordField;
	public boolean videoON = true;
	final static VideoPanel2 videoPanel = new VideoPanel2();

	private static final String STATUS_PHOTO = "Veuillez prendre une photo pour vous identifier";
	private static final String STATUS_BIO_Success = "veuiller inserer votre carte d'acc�s";
	private static final String STATUS_CARD_failed = "carte erron�e";
	private static final String STATUS_CARD_Success = "inserer votre mot de passe";
	private static final String STATUS_MDP_failed = "  Mot de passe �rron�, veuillez resaisir";
	private static final String STATUS_MDP_Success = "Bienvenue";
	private static final String STATUS_SAVE_failed = "Champ non compl�t�";

	private JButton button;
	private JLabel statut_lbl;
	private JLabel name_lbl;
	private JLabel iDcard_lbl;
	private boolean biosuccess = false;

	private Mat snapshot = null;
	private String histo = "";
	private byte[] histo_secure = null;
	
	/**
	 * Launch the application.
	 */

	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					InitialisationFrame frame = new InitialisationFrame();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public InitialisationFrame() {
		// TODO Auto-generated constructor stub

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 680, 650);
		setTitle("Capture des données biométriques");
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);

		contentPane.add(videoPanel, BorderLayout.CENTER);

		JPanel panel = new JPanel();
		contentPane.add(panel, BorderLayout.SOUTH);
		panel.setLayout(new GridLayout(1, 1, 0, 0));

		JPanel panel_1 = new JPanel();
		panel.add(panel_1);
		panel_1.setLayout(new GridLayout(0, 2, 0, 0));

		button = new JButton(STATUS_PHOTO);
		panel_1.add(button);

		JPanel panel_3 = new JPanel();
		panel_3.setBackground(Color.WHITE);
		panel_1.add(panel_3);
		panel_3.setLayout(new GridLayout(4, 1, 0, 0));

		statut_lbl = new JLabel(STATUS_PHOTO);
		statut_lbl.setBackground(Color.WHITE);
		panel_3.add(statut_lbl);

		name_lbl = new JLabel("Name : ");
		name_lbl.setBackground(Color.WHITE);
		name_lbl.setVisible(true);
		panel_3.add(name_lbl);

		iDcard_lbl = new JLabel("ID card :");
		iDcard_lbl.setBackground(Color.WHITE);
		iDcard_lbl.setVisible(true);
		panel_3.add(iDcard_lbl);

		JPanel panel_4 = new JPanel();
		panel_4.setBackground(Color.WHITE);
		panel_3.add(panel_4);
		GridBagLayout gbl_panel_4 = new GridBagLayout();
		gbl_panel_4.columnWidths = new int[] { 81, 6, 89, 0 };
		gbl_panel_4.rowHeights = new int[] { 23, 0 };
		gbl_panel_4.columnWeights = new double[] { 1.0, 0.0, 0.0,
				Double.MIN_VALUE };
		gbl_panel_4.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
		panel_4.setLayout(gbl_panel_4);

		passwordField = new JPasswordField();
		passwordField.setEditable(true);
		GridBagConstraints gbc_passwordField = new GridBagConstraints();
		gbc_passwordField.fill = GridBagConstraints.BOTH;
		gbc_passwordField.gridwidth = 2;
		gbc_passwordField.insets = new Insets(0, 0, 0, 5);
		gbc_passwordField.gridx = 0;
		gbc_passwordField.gridy = 0;
		panel_4.add(passwordField, gbc_passwordField);

		JButton ok = new JButton("Enregistrer les donnees");
		GridBagConstraints gbc_ok = new GridBagConstraints();
		gbc_ok.fill = GridBagConstraints.HORIZONTAL;
		gbc_ok.anchor = GridBagConstraints.NORTH;
		gbc_ok.gridx = 2;
		gbc_ok.gridy = 0;
		panel_4.add(ok, gbc_ok);

		// action Listener
		button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.out.println("je clic");
				if (videoON) {
					// take picture
					videoON = false;
					snapshot = videoPanel.capture();
					videoPanel.stop();
					button.setText("lancer la video");
					statut_lbl.setText("Analyse Biom�trique en cours");
					
					// appelle de la fonction biom�trique
					long start = System.currentTimeMillis();
					Mat untouched = snapshot.clone();
					Mat draw = snapshot.clone();
					
					/*FormDetector2 fd = new FormDetector2();
					Point[] eye_zone = FormDetector2.findFace(snapshot, "", draw);
					Point[] eye = FormDetector2.findEye(snapshot, eye_zone, "", draw);*/
					//Point[] eye = FormDetector2.irisRecognitionLD(snapshot, draw, "");
					Point[] eye = FormDetector2.irisRecognitionHD(snapshot, draw, "");
					histo = FormDetector2.computeHisto(untouched, eye);
					System.out.println("time: "+(System.currentTimeMillis()-start)+"ms");
					
					// affiche le resultat a l'ecran
					videoPanel.AfficherImage(draw);
					
					// TODO à faire une fois sur le pc lecteur
					final String ksPath = "C:\\Users\\B182JS\\workspace\\projet_SmartCard\\bin\\aesKeyStore.keystore";
					final char[] ksPassword = {'t','o','t','o'};
					final char[] keyPassword = {'t','o','t','o'};
					String alias = "aesKey";
					
					//AES256.createAESKeyStore(ksPath, ksPassword, keyPassword, alias);
					
					// TODO crypt l'histo
					SecretKey aesKey = null;
					
					try {
						// Load Key From Keystore
						aesKey = AES256.loadKeyFromKeyStore(ksPath, ksPassword, keyPassword, alias);
						
						// Encrypt cipher
						Cipher encryptCipher;
						encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
						encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
						
						// Crypt
						byte[] encryptedData = AES256.encrypt(histo.getBytes(), aesKey, encryptCipher);
						histo_secure = encryptedData;
					} catch (NoSuchAlgorithmException e) {
						e.printStackTrace();
					} catch (NoSuchPaddingException e) {
						e.printStackTrace();
					} catch (InvalidKeyException e) {
						e.printStackTrace();
					}
					
				} else {
					button.setText("prendre une photo");
					statut_lbl.setText(STATUS_PHOTO);
					videoON = true;
					videoPanel.play();
				}
			}
		});

		ok.addActionListener(new ActionListener() {
			@SuppressWarnings("deprecation")
			@Override
			public void actionPerformed(ActionEvent e) {
				String cardUID = null;
				/*if (!biosuccess) { 
					statut_lbl.setText(STATUS_PHOTO);// Test biom�trique
				} else if (passwordField.getText().equalsIgnoreCase("")||name_lbl.getText().equalsIgnoreCase("name :")||iDcard_lbl.getText().equalsIgnoreCase("ID card : ")) {
					statut_lbl.setText(STATUS_SAVE_failed);
				} else {*/
					LeGroupe4Biometric.setWaitForPasswordControl();
					
					//TODO recuperer l id de la card inserer
					/*try {
						cardUID = SmartCard.toHex(LeGroupe4Biometric.getSmartCard().getUidBytes());
					} catch (CardException e2) {
						e2.printStackTrace();
					}
					
					Session session = HibernateUtil.getSession();
					Transaction tx = session.beginTransaction();
					AuthCardData card = new AuthCardData();
					try{
						 card = (AuthCardData) session.createCriteria(AuthCardData.class).add(Restrictions.like("card_uid", cardUID)).list().get(0);
					}catch(Exception e1){
						statut_lbl.setText(STATUS_CARD_failed);
					}
					User user = new User();
					user = card.getUser();
					
					//TODO changer les champs voulus
					//TODO ATTENTION ! ne faire ça que si l'user rentre un mdp valide !
					
					//idee bloquer par un while ici le temps que LeGroupe4Biometric fasse
					//la verification du mdp, et debloquer le while lorsque la verif est correcte, puis envoyer!
					
					//ou alors, faire la verif ici mais p'têtre plus chiant =/
					
					user.setUser_biometric_data(histo_secure);
					
					session.save(user);
					tx.commit();
					
					// fermeture de session
					session.close();*/

					System.out.println("Biometric data save in base!");
				}
			//}
		});
		this.setVisible(true);
		videoPanel.play();
		managementStatut(01);
		LeGroupe4Biometric.setWaitForCard();
	}

	public void managementStatut(int statusCode) {
		switch (statusCode) {
		case 01:
			// biosuccess
			statut_lbl.setText(STATUS_BIO_Success);
			name_lbl.setVisible(true);
			//button.setEnabled(false);
			;
			break;
		case 02:
			// bioFailed
			statut_lbl.setText(STATUS_PHOTO);
			;
			break;
		case 03:
			statut_lbl.setText(STATUS_CARD_Success);
			passwordField.setEditable(true);
			;
			break;
		case 04:
			statut_lbl.setText(STATUS_CARD_failed);
			;
			break;
		case 05:
			statut_lbl.setText(STATUS_MDP_failed);
			;
			break;
		case 06:
			statut_lbl.setText(STATUS_MDP_Success);
			button.setEnabled(true);
			;
			break;
		default:

		}
	}
	
	/**
	 * modifie le texte du label
	 * @param label le label ? modifier
	 * @param text le nouveau texte du label
	 */
	public void updateLabelText(JLabel label, String text){
		label.setText(text);
	}

	/**
	 * permet d'autoriser ou interdire l'?dition d'un champ texte
	 * @param tf champ texte ou mot de passe
	 * @param b  'true' : autorise l'?dition, 'false' interdit l'?dition
	 */
	public void updateFieldEdition(JTextField tf, boolean b){
		tf.setEditable(b);
	}

	public void updateFieldText(JTextField tf, String text){
		tf.setText(text);
	}
	
	public void updatePasswordText(JPasswordField pf, String text){
		pf.setText(text);
	}
	
	public void updateLabelVisible(JLabel jl, boolean b){
		jl.setVisible(b);
	}
	
	public void updatePasswordVisible(JPasswordField pf, boolean b){
		pf.setVisible(b);
	}

	public JPasswordField getPasswordField() {
		return passwordField;
	}

	public JLabel getStatutLabel() {
		return statut_lbl;
	}

	public JLabel getNameLabel() {
		return name_lbl;
	}

	public JLabel getiDcardLabel() {
		return iDcard_lbl;
	}

	public byte[] getHisto_secure() { return histo_secure; }
	
}
